/* Nate Deisinger (ndeisinger@wisc.edu)
 *
 * This file is part of soot-csi, a project to apply lightweight
 * instrumentation to Java programs to facilitate debugging through
 * the Soot analysis framework.
 *
 * Copyright (c) 2014, Nate Deisinger, University of Wisconsin-Madison
 *   Madison, Wisconsin 53715
 *   All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor,
 *   Boston, MA  02110-1301
 *   USA
 * or retrieve version 2.1 at their website:
 *   http://www.gnu.org/licenses/lgpl-2.1.html
 */
package uwmadison.soot.analysis;

import soot.G;
import soot.Trap;

/**
 * A specialized CFG edge class we use in our path profiling work.
 * @author Nate Deisinger
 */
public class CFGEdge
{
    private final CFGNode from;
    private final CFGNode to;
    private int val;
    private int instr_val;
    private boolean isBackedge;
    private boolean isDummyEdge;
    private CFGEdge associatedInDummyEdge;
    private CFGEdge associatedOutDummyEdge;
    private Trap trap;

    public CFGEdge(CFGNode from, CFGNode to)
    {
        this.from = from;
        this.to = to;
        this.isBackedge = false;
        this.isDummyEdge = false;
        this.trap = null;
        this.val = 0;
        this.instr_val = 0;
        this.associatedInDummyEdge = null;
        this.associatedOutDummyEdge = null;
    }

    public void setAssociatedDummyEdges(CFGEdge inEdge, CFGEdge outEdge)
    {
        this.associatedInDummyEdge = inEdge;
        this.associatedOutDummyEdge = outEdge;
    }

    public CFGEdge getAssociatedDummyEdge()
    {
        return this.associatedInDummyEdge;
    }

    public void setBackedge(boolean val)
    {
        this.isBackedge = val;
    }

    public boolean isBackedge()
    {
        return this.isBackedge;
    }

    public void setDummyEdge(boolean val)
    {
        this.isDummyEdge = val;
    }

    public boolean isDummyEdge()
    {
        return this.isDummyEdge;
    }

    public void setInstrVal(int val)
    {
        this.instr_val = val;
    }

    public int getInstrVal()
    {
        if (this.isBackedge())
        {
            if ((this.associatedInDummyEdge == null) || (this.associatedOutDummyEdge == null))
            {
                throw new RuntimeException("Error: backedge does not have appropriate dummy edges");
            }
            if (this.associatedOutDummyEdge.getInstrVal() != 0)
            {
                G.v().out.println("Warning: Backedge " + this + " has non-zero exit dummy edge " + this.associatedOutDummyEdge);
            }
            return (this.associatedInDummyEdge.getInstrVal());// + this.associatedOutDummyEdge.getInstrVal());
        }
        return instr_val;
    }

    public void setVal(int val)
    {
        this.val = val;
    }

    public int getVal()
    {
        return val;
    }

    public CFGNode getFrom()
    {
        return from;
    }

    public CFGNode getTo()
    {
        return to;
    }

    public String toString()
    {
        return "from: " + from.getBlock().getIndexInMethod() + ", to: " 
                + to.getBlock().getIndexInMethod() + ", val: " + val;
    }

    public void setTrap(Trap t)
    {
        this.trap = t;
    }

    public Trap getTrap()
    {
        return this.trap;
    }
}